#include"Camera.h"

/////////////////
//include
/////////////////
#include"Key.h"
#include"ANX.h"
#include<time.h>
#include"../CXBurst/Math.h"
#include"../CXBurst/Debug.h"
/////////////////
//prottype
/////////////////

/////////////////
//const
/////////////////


Camera::Camera(DeviceContext* device_context,Device* device, Vector3D pos,Vector3D look,Vector3D up)
{
	srand(time(NULL));
	this->pos	= pos;
	this->look	= look;
	this->up	= up;
	this->device_context = device_context;
	angle = PI/4;
	near_ = 0.1f;
	far_ = 500000.0f;
	if(!device)
		return;
	camera_matrix =  XMMatrixTranspose( XMMatrixLookAtLH(XMLoadFloat3(&pos),XMLoadFloat3(&look),XMLoadFloat3(&up)));

	perspective_matrix =XMMatrixTranspose(XMMatrixPerspectiveFovLH(angle,((float)WINDOW_X)/WINDOW_Y,near_,far_));
	camera_buffer =  device->CreateConstantBuffer((void*)&camera_matrix,sizeof(XMMATRIX));
	perspective_buffer =  device->CreateConstantBuffer((void*)&perspective_matrix,sizeof(XMMATRIX));
	shake_count = 0;
}
Camera::~Camera()
{
}
void Camera::GetTransFormVector(Vector3D* trans)
{
	Vector3D z = -(look-pos).Normalize();
	Vector3D x = up.Cross(z);//z.Cross(up);
	Vector3D y = z.Cross(x);
	Vector3D trans_x = Vector3D(x.x,y.x,z.x);
	Vector3D trans_y = Vector3D(x.y,y.y,z.y);
	Vector3D trans_z = Vector3D(x.z,y.z,z.z);
	trans[0] = trans_x;
	trans[1] = trans_y;
	trans[2] = trans_z;
}
void Camera::Update()
{

	float speed = 1;
	/*if(Key::IsPushing(VK_SHIFT))
	{
	if(Key::IsPushing(VK_UP))
	pos.y -= speed;
	if(Key::IsPushing(VK_DOWN))
	pos.y+= speed;
	if(Key::IsPushing(VK_RIGHT))
	pos.x-= speed;
	if(Key::IsPushing(VK_LEFT))
	pos.x+= speed;
	if(Key::IsPushing('S'))
	pos.z-= speed;
	if(Key::IsPushing('A'))
	pos.z+= speed;
	}
	else
	{
	if(Key::IsPushing(VK_UP))
	{
	pos.y+= speed;
	look.y+= speed;
	}
	if(Key::IsPushing(VK_DOWN))
	{
	pos.y -= speed;
	look.y -= speed;
	}
	if(Key::IsPushing(VK_RIGHT))
	{
	pos.x+= speed;
	look.x+= speed;
	}
	if(Key::IsPushing(VK_LEFT))
	{
	pos.x-= speed;
	look.x-= speed;
	}
	if(Key::IsPushing('S'))
	{
	pos.z-= speed;
	look.z-= speed;
	}
	if(Key::IsPushing('A'))
	{
	pos.z+= speed;
	look.z+= speed;
	}
	}*/
	if(!device_context)
		return;
	if(!device_context)
		return;
	camera_matrix =  XMMatrixTranspose( XMMatrixLookAtLH(XMLoadFloat3(&pos),XMLoadFloat3(&look),XMLoadFloat3(&up)));
	perspective_matrix =XMMatrixTranspose(XMMatrixPerspectiveFovLH(angle,((float)WINDOW_X)/WINDOW_Y,near_,far_));
	device_context->UpdateBuffer(camera_buffer,&camera_matrix,sizeof(XMMATRIX));
	device_context->UpdateBuffer(perspective_buffer,&perspective_matrix,sizeof(XMMATRIX));
}
void Camera::SetMatrix()
{
	device_context->SetConstantBuffer(camera_buffer,0);
	device_context->SetConstantBuffer(perspective_buffer,1);
}
Matrix Camera::GetBillBoardMatrix()
{
	XMVECTOR vec = XMVECTOR();
	Vector3D tmp_pos = Vector3D();
	Vector3D tmp_look = (look - pos);//GetDirection();

	XMVECTOR tmp_pos_vec = tmp_pos.Xm();
	XMVECTOR tmp_look_vec = tmp_look.Xm();

	Matrix tmp_matrix = XMMatrixLookAtLH(tmp_pos_vec,tmp_look_vec,XMLoadFloat3(&up));
	XMMATRIX tmp_inv_matrix = XMMatrixInverse(&vec, tmp_matrix.Xm());
	return tmp_inv_matrix;
}
Matrix Camera::GetBillBoardMatrixAxis(const Vector3D& axis,const Vector3D& pos)
{
	XMVECTOR vec = XMVECTOR();
	Vector3D tmp_pos = Vector3D();
	Vector3D tmp_look = (look - this->pos);//GetDirection();
	float tmp_y_rad = axis.BitWeenRad(Vector3D::UP);
	Vector3D tmp_cross = axis.Cross(Vector3D::UP);
	//Vector3D tmp_rot_cross = axis.Cross(Vector3D::LEFT);
	//tmp_rot_cross = tmp_rot_cross.GetIsZero() ? Vector3D::UP : tmp_rot_cross;

	float tmp_rot = tmp_look.Normalize().Dot(tmp_cross.Normalize());
	float signe = 1;
	if(tmp_rot < 0)
	{
		tmp_look =  tmp_look.RotationAxis(tmp_cross.Cross(tmp_look.Normalize()),PI);
	}
	CXBurst::DebugPrint(tmp_rot,"tmp_rot");
	tmp_look = tmp_look.RotationAxis(tmp_cross,tmp_y_rad);
	tmp_look.y = 0;
	tmp_look = tmp_look.RotationAxis(tmp_cross,-tmp_y_rad).Normalize();



	XMVECTOR tmp_pos_vec = tmp_pos.Xm();
	XMVECTOR tmp_look_vec = tmp_look.Normalize().Xm();

	Matrix tmp_matrix = XMMatrixLookAtLH(tmp_pos_vec,tmp_look_vec,up.Xm());
	XMMATRIX tmp_inv_matrix = XMMatrixInverse(&vec, tmp_matrix.Xm());
	return Matrix(tmp_inv_matrix) ;
}
Vector2D Camera::ChangeScreenPos(const Vector3D& pos)
{
	Vector3D tmp_pos = Vector3D();
	tmp_pos = pos	*	(perspective_matrix*	camera_matrix).Transpose();
	return Vector2D(tmp_pos.x,tmp_pos.y);
}
void Camera::Shake(int count)
{

	look+=Vector3D(rand()%10-5,rand()%10-5,0);
}